UNIT REMUNIT ;{ This is REMUNIT for a Poly }   {xL PRINTER: }

INTERFACE

{============== Copyright Notice =======================}
        {$C Copyright 1980, 1981 by Robert W. Peterson }
{============== Copyright Notice =======================}


{============================================================
  This is a separate compilation unit intended to stand 
  between application code and a communication line.
  Implementation of this unit follows the specifications
  and suggestions set out in the Feburary 1981 draft of the
  USUS (UCSD p-System User Society) remote unit specification.
  
  This unit will interface to the following model codes:
        POLYMORPHIC

  The following routines are not functional:
        CR_BREAK
        CR_CLEARTOSEND
        CR_DIAL
        CR_DIALTONE
        CR_SETADDRESS
        CR_SETCOMMUNICATIONS
        CR_SETDTR
        CR_SETRTS
        
  The following routines contain calls to UnitClear:
        CR_ANSWER

 ============================================================}


{============================================================
                Change Log
                ====== ===
  Date     What change was made & Who made the change
---------  ----------------------------------------------------
16 Nov 81  Bring up to actually adopted standard - Bob Peterson
03 Aug 81  Convert to IV.0 - Bob Peterson
28 Mar 81  Original code - Bob Peterson


 ============================================================}
{$P+}

TYPE
  CR_DIALRESULT     = ( CR_OFF_HOOK, 
                        CR_DIALERROR,
                        CR_NOAUTODIAL ) ;
  CR_BAUD_RESULT    = ( CR_BAD_PARAMETER,
                        CR_BAD_RATE,
                        CR_SET_OK,
                        CR_SELECT_NOT_SUPPORTED ) ;
  CR_WHOAMI         = ( CR_ORIG,
                        CR_ANS ) ;
  CR_REM_PORT       =  PACKED RECORD
                        PART1   : INTEGER ;
                        PART2   : INTEGER ;
                        END ; { CR_REM_PORT }
  CR_STATE          = ( CR_ON,
                        CR_OFF,
                        CR_AUTO ) ;

VAR
  CR_ATTENCHAR          : CHAR ;
  CR_CURRENT_PORT       : CR_REM_PORT ;

{       Initialization and termination routines. }
PROCEDURE CR_COMMINIT(  DIR             : CR_WHOAMI ;
                        ATTENTION_CHAR  : CHAR ;
                    VAR REMOTE_EXISTS   : BOOLEAN ;
                    VAR DIALER_EXITST   : BOOLEAN ) ;

PROCEDURE CR_COMMQUIT ;


{       Input status. }
FUNCTION  CR_KBSTAT                     : BOOLEAN ;
FUNCTION  CR_REMSTAT                    : BOOLEAN ;


{       Input/Output operations. }
FUNCTION  CR_GETKB                      : CHAR ;
FUNCTION  CR_GETREM                     : CHAR ;
PROCEDURE CR_PUTREM(                  C : CHAR ) ;


{       Control procedures. }
PROCEDURE CR_ANSWER ;
PROCEDURE CR_BREAK ;
FUNCTION  CR_CARRIER                    : BOOLEAN ;
FUNCTION  CR_CLEARTOSEND                : BOOLEAN ;
PROCEDURE CR_DELAY(     TENTHS          : INTEGER ) ;
PROCEDURE CR_DIAL(      NUMBER          : STRING ;
                        WAITCHAR        : CHAR
                    VAR RESULT          : CR_DIALRESULT ) ;
FUNCTION  CR_DIALTONE                   : BOOLEAN ;
PROCEDURE CR_HOOK(      ON_HOOK         : BOOLEAN ) ;
FUNCTION  CR_RINGING                    : BOOLEAN ;
PROCEDURE CR_SETADDRESS(HIGHADDR        : INTEGER ;
                        LOWADDR         : INTEGER ;
                        VECTOR          : INTEGER ) ;
PROCEDURE CR_SETCOMMUNICATIONS(
                        PARITY          : BOOLEAN ;
                        EVEN            : BOOLEAN ;
                        RATE            : INTEGER ;
                        CHARBITS        : INTEGER ;
                        STOPBITS        : INTEGER ;
                        DIR             : CR_WHOAMI ;
                        MODEL           : STRING ;
                    VAR RESULT          : CR_BAUD_RESULT ) ;
PROCEDURE CR_SET_DTR(   NEW_STATE       : CR_STATE ) ;
PROCEDURE CR_SET_RTS(   NEW_STATE       : CR_STATE ) ;
                    

IMPLEMENTATION
{$P+}{ Page here so the option is not in the interface text. }
CONST
  DEFAULT_RATE          =  300 ;
  DEFAULT_MODE          = TRUE ; { Default to parity enabled. }
  DEFAULT_PARITY        = TRUE ; { Default to even parity.    }
  DEFAULT_CHARBITS      =    7 ; { Default to seven data bits.}
  DEFAULT_STOPBITS      =    1 ; { Default to one stop bits.  }
  HUNG_UP               = TRUE ;
  KB_UNIT               =    2 ;
  REMIN_UNIT            =    7 ;
  REMOUT_UNIT           =    8 ;
  TIMER                 =  250 ;

TYPE
  TRICK                 = PACKED RECORD
                          CASE INTEGER OF
                          1:(A : PACKED ARRAY[0..80] OF CHAR);
                          2:(S : STRING[80]);
                          3:(I : INTEGER;
                             J : INTEGER);
                          4:(L : ARRAY[0..39] OF INTEGER);
                          5:(B : ARRAY[0..39] OF BOOLEAN);
                          6:(C : PACKED RECORD
                                 CHARL  : CHAR ;
                                 CHARR  : CHAR 
                                 END ) ;
                          END ; { TRICK }

VAR
  BAUD_SETTABLE         : BOOLEAN ;
  CONTROL               : INTEGER ;
  CURRENT_BAUD          : INTEGER ;
  DTR_STATE             : CR_STATE ;
  MODEL_ID              : STRING ;
  OFF_HOOK              : BOOLEAN ;
  RTS_STATE             : CR_STATE ;
  UNIT_CARRIER          : BOOLEAN ;
{$P+}
{  ---------------------------------------------------------  }
{               Control Procedures                            }
{  ---------------------------------------------------------  }

PROCEDURE CR_ANSWER ;
VAR
  WAITING               : BOOLEAN ;
BEGIN
  WAITING := TRUE ;
  WHILE WAITING DO
    BEGIN
    WAITING := NOT CR_CARRIER ;
    IF WAITING
      THEN
        IF CR_KBSTAT
          THEN
            WAITING := CR_GETKB <> CR_ATTENCHAR ;
    END ;
  OFF_HOOK := NOT WAITING ;
  IF NOT WAITING
    THEN
      BEGIN
      UNITCLEAR( REMIN_UNIT ) ;
      UNITCLEAR( REMOUT_UNIT ) ;
      END ;
END ; { CR_ANSWER }

PROCEDURE CR_BREAK ;
BEGIN
END ;

FUNCTION  CR_CARRIER{ : BOOLEAN } ;
BEGIN
  CR_CARRIER := UNIT_CARRIER ;
  OFF_HOOK   := UNIT_CARRIER ;
END ; { CR_CARRIER }

FUNCTION  CR_CLEARTOSEND{ : BOOLEAN } ;
BEGIN
  CR_CLEARTOSEND := TRUE ;
END ; { CR_CLEARTOSEND }

PROCEDURE CR_DELAY{ TENTHS : INTEGER } ;
VAR
  I             : INTEGER ;
BEGIN
  I := TIMER ;
  WHILE I > 0 DO
    I := I - 1 ;
END ; { CR_DELAY }

PROCEDURE CR_DIAL{ NUMBER       : STRING ;
               VAR RESULT       : CR_DIAL_RESULT } ;
BEGIN
  RESULT := CR_NOAUTODIAL ;
END ; { CR_DIAL }

FUNCTION CR_DIALTONE ;
BEGIN
  CR_DIALTONE := TRUE ;
END ;

PROCEDURE CR_HOOK{ ON_HOOK      : BOOLEAN } ;
BEGIN
  OFF_HOOK := NOT ON_HOOK ;
  UNIT_CARRIER := OFF_HOOK ;
END ; { CR_HOOK }

FUNCTION CR_RINGING { : BOOLEAN } ;
BEGIN
  CR_RINGING := TRUE ;
END ;
{$P+}
{  ---------------------------------------------------------  }
{               Status Procedures                             }
{  ---------------------------------------------------------  }

FUNCTION  CR_KBSTAT{ : BOOLEAN } ;
VAR
  A     : TRICK ;
BEGIN
  UNITSTATUS( KB_UNIT, A, 1 ) ;
  CR_KBSTAT := A.I > 0 ;
END ; { CR_KBSTAT }

FUNCTION  CR_REMSTAT{ : BOOLEAN } ;
VAR
  A     : TRICK ;
BEGIN
  UNITSTATUS( REMIN_UNIT, A, 1 ) ;
  CR_REMSTAT := A.I > 0 ;
END ; { CR_REMSTAT }
{$P+}
{  ---------------------------------------------------------  }
{               Input/Output Procdures                        }
{  ---------------------------------------------------------  }

FUNCTION  CR_GETKB{ : CHAR } ;
VAR
  ARAY                  : TRICK ;
BEGIN
  UNITREAD( KB_UNIT, ARAY.A, 1,, 12 ) ;
  CR_GETKB := ARAY.A[0] ;
END ; { CR_GETKB }

FUNCTION  CR_GETREM{ : CHAR } ;
VAR
  ARAY                  : TRICK ;
BEGIN
  UNITREAD( REMIN_UNIT, ARAY.A, 1,, CONTROL ) ;
  CR_GETREM := ARAY.A[0] ;
END ; { CR_GETREM }

PROCEDURE CR_PUTREM{ C : CHAR } ;
VAR
  P                     : TRICK ;
BEGIN
  P.A[0] := C ;
  UNITWRITE( REMOUT_UNIT, P.A, 1, 0, CONTROL ) ;
END ; { CR_PUTREM }
{$P+}
{  ---------------------------------------------------------  }
{               Initialization/Termination Procedures         }
{  ---------------------------------------------------------  }

PROCEDURE CR_SETADDRESS{        HIGHADDR        : INTEGER ;
                                LOWADDR         : INTEGER ;
                                VECTOR          : INTEGER } ;
BEGIN
  WITH CR_CURRENT_PORT DO
    BEGIN
    PART1 := HIGHADDR ;
    PART2 := LOWADDR ;
    END ;
END ; { CR_SETADDRESS }

PROCEDURE CR_SETDTR ;
BEGIN
END ;

PROCEDURE CR_SETRTS ;
BEGIN
END ;

PROCEDURE CR_SETCOMMUNICATIONS{
                        PARITY          : BOOLEAN ;
                        EVEN            : BOOLEAN ;
                        RATE            : INTEGER ;
                        CHARBITS        : INTEGER ;
                        STOPBITS        : INTEGER ;
                        DIR             : CR_WHOAMI ;
                        MODEL           : STRING ;
                    VAR RESULT          : CR_BAUD_RESULT } ;
BEGIN
  CONTROL       :=    12 ;
  BAUD_SETTABLE := FALSE ;
  IF (MODEL = 'POLYMORPHIC') OR
     (MODEL = 'Polymorphic') OR
     (MODEL = 'POLY'       ) OR
     (MODEL = 'Poly'       )
    THEN
      RESULT        := CR_SET_OK
    ELSE
      RESULT        := CR_SELECT_NOT_SUPPORTED ;
END ; { CR_SETCOMMUNICATIONS }

PROCEDURE CR_COMMINIT{  DIR             : CR_WHOAMI ;
                        ATTENTION_CHAR  : CHAR ;
                    VAR REMOTE_EXISTS   : BOOLEAN ;
                    VAR DIALER_EXITST   : BOOLEAN } ;
VAR
  RESULT                : CR_BAUD_RESULT ;
PROCEDURE NOT_THERE ;
BEGIN
  PAGE( OUTPUT ) ;
  GOTOXY( 0, 10 ) ;
  WRITELN(' ':20, 'Required unit failed UNITCLEAR!') ;
  WRITELN(' ':20, 'Program will terminate.') ;
  EXIT( PROGRAM ) ;
END ;
BEGIN
  { Set no auto-dial. }
  DIALER_EXISTS := FALSE ;
  
  { Check that the required units exist. }
  REMOTE_EXISTS := TRUE ;
  UNITCLEAR( REMIN_UNIT ) ;
  IF IORESULT <> 0
    THEN
      NOT_THERE ;
  UNITCLEAR( REMOUT_UNIT ) ;
  IF IORESULT <> 0
    THEN
      NOT_THERE ;
  
  UNIT_CARRIER := FALSE ;
  CR_HOOK( HUNG_UP ) ;
  
  MODEL_ID      := '' ;
  DTR_STATE     := CR_AUTO ;
  RTS_STATE     := CR_AUTO ;
  OFF_HOOK      := FALSE ;
  BAUD_SETTABLE :=  TRUE ;
  CR_ATTENCHAR  := ATTENTION_CHAR ;

  CR_SETCOMMUNICATIONS(
                        DEFAULT_MODE,
                        DEFAULT_PARITY,
                        DEFAULT_RATE,
                        DEFAULT_CHARBITS,
                        DEFAULT_STOPBITS,
                        CR_ORIG,
                        'POLYMORPHIC',
                        RESULT ) ;
  BAUD_SETTABLE := RESULT = CR_SELECT_NOT_SUPPORTED ;
END ; { CR_COMMINIT }


PROCEDURE CR_COMMQUIT ;
VAR
  RESULT                : CR_BAUD_RESULT ;
BEGIN
  CR_HOOK( HUNG_UP ) ;
  IF BAUD_SETTABLE
    THEN
      CR_SETCOMMUNICATIONS(
                        DEFAULT_MODE,
                        DEFAULT_PARITY,
                        DEFAULT_RATE,
                        DEFAULT_CHARBITS,
                        DEFAULT_STOPBITS,
                        CR_ORIG,
                        'POLYMORPHIC',
                        RESULT ) ;

END ; { CR_COMMQUIT }
BEGIN
END.

